from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import logging
import time
import os


class Base:
    """
    UI自动化测试基础页面类
    封装了常用的页面操作方法，所有页面类都应继承此类
    """

    def __init__(self, driver):
        """
        初始化BasePage

        Args:
            driver: WebDriver实例
        """
        self.driver = driver
        self.timeout = 30  # 默认超时时间
        self.logger = logging.getLogger(__name__)

    def open_url(self, url):
        """
        打开指定URL

        Args:
            url: 要打开的网址
        """
        self.logger.info(f"打开URL: {url}")
        self.driver.get(url)

    def find_element(self, locator, timeout=None):
        """
        查找单个元素

        Args:
            locator: 定位器，格式为(定位方式, 定位表达式)
            timeout: 超时时间，默认使用类默认超时时间

        Returns:
            WebElement: 找到的元素

        Raises:
            TimeoutException: 超时未找到元素
        """
        if timeout is None:
            timeout = self.timeout

        try:
            self.logger.info(f"查找元素: {locator}")
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located(locator)
            )
            return element
        except TimeoutException:
            self.logger.error(f"查找元素超时: {locator}")
            raise

    def find_elements(self, locator, timeout=None):
        """
        查找多个元素

        Args:
            locator: 定位器，格式为(定位方式, 定位表达式)
            timeout: 超时时间，默认使用类默认超时时间

        Returns:
            list: 找到的元素列表
        """
        if timeout is None:
            timeout = self.timeout

        try:
            self.logger.info(f"查找多个元素: {locator}")
            elements = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_all_elements_located(locator)
            )
            return elements
        except TimeoutException:
            self.logger.warning(f"查找多个元素超时: {locator}")
            return []

    def click(self, locator, timeout=None):
        """
        点击元素

        Args:
            locator: 定位器
            timeout: 超时时间
        """
        element = self.find_element(locator, timeout)
        self.logger.info(f"点击元素: {locator}")
        element.click()

    def input_text(self, locator, text, timeout=None):
        """
        输入文本

        Args:
            locator: 定位器
            text: 要输入的文本
            timeout: 超时时间
        """
        element = self.find_element(locator, timeout)
        self.logger.info(f"在元素 {locator} 中输入文本: {text}")
        # element.clear()
        element.send_keys(text)


    def get_text(self, locator, timeout=None):
        """
        获取元素文本

        Args:
            locator: 定位器
            timeout: 超时时间

        Returns:
            str: 元素文本
        """
        element = self.find_element(locator, timeout)
        text = element.text
        self.logger.info(f"获取元素 {locator} 的文本: {text}")
        return text

    def get_attribute(self, locator, attribute, timeout=None):
        """
        获取元素属性

        Args:
            locator: 定位器
            attribute: 属性名
            timeout: 超时时间

        Returns:
            str: 属性值
        """
        element = self.find_element(locator, timeout)
        value = element.get_attribute(attribute)
        self.logger.info(f"获取元素 {locator} 的属性 {attribute}: {value}")
        return value

    def is_element_visible(self, locator, timeout=None):
        """
        判断元素是否可见

        Args:
            locator: 定位器
            timeout: 超时时间

        Returns:
            bool: 是否可见
        """
        try:
            if timeout is None:
                timeout = self.timeout

            WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located(locator)
            )
            self.logger.info(f"元素 {locator} 可见")
            return True
        except TimeoutException:
            self.logger.info(f"元素 {locator} 不可见")
            return False

    def is_element_present(self, locator, timeout=None):
        """
        判断元素是否存在（不一定可见）

        Args:
            locator: 定位器
            timeout: 超时时间

        Returns:
            bool: 是否存在
        """
        try:
            self.find_element(locator, timeout)
            self.logger.info(f"元素 {locator} 存在")
            return True
        except TimeoutException:
            self.logger.info(f"元素 {locator} 不存在")
            return False

    def wait_for_element_clickable(self, locator, timeout=None):
        """
        等待元素可点击

        Args:
            locator: 定位器
            timeout: 超时时间

        Returns:
            WebElement: 可点击的元素
        """
        if timeout is None:
            timeout = self.timeout

        try:
            self.logger.info(f"等待元素可点击: {locator}")
            element = WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable(locator)
            )
            return element
        except TimeoutException:
            self.logger.error(f"等待元素可点击超时: {locator}")
            raise

    def switch_to_frame(self, locator, timeout=None):
        """
        切换到iframe

        Args:
            locator: iframe的定位器
            timeout: 超时时间
        """
        if timeout is None:
            timeout = self.timeout

        try:
            self.logger.info(f"切换到iframe: {locator}")
            WebDriverWait(self.driver, timeout).until(
                EC.frame_to_be_available_and_switch_to_it(locator)
            )
        except TimeoutException:
            self.logger.error(f"切换到iframe超时: {locator}")
            raise

    def switch_to_default_content(self):
        """
        切换回默认内容
        """
        self.logger.info("切换回默认内容")
        self.driver.switch_to.default_content()

    def switch_to_window(self, window_handle=None):
        """
        切换到指定窗口

        Args:
            window_handle: 窗口句柄，如果为None则切换到最新窗口
        """
        if window_handle is None:
            # 切换到最新打开的窗口
            window_handle = self.driver.window_handles[-1]

        self.logger.info(f"切换到窗口: {window_handle}")
        self.driver.switch_to.window(window_handle)

    def execute_script(self, script, *args):
        """
        执行JavaScript脚本

        Args:
            script: JavaScript代码
            *args: 参数

        Returns:
            JavaScript执行结果
        """
        self.logger.info(f"执行JavaScript脚本: {script}")
        return self.driver.execute_script(script, *args)

    def scroll_to_element(self, locator, timeout=None):
        """
        滚动到元素位置

        Args:
            locator: 元素定位器
            timeout: 超时时间
        """
        element = self.find_element(locator, timeout)
        self.logger.info(f"滚动到元素: {locator}")
        self.execute_script("arguments[0].scrollIntoView(true);", element)

    def hover(self, locator, timeout=None):
        """
        鼠标悬停到元素

        Args:
            locator: 元素定位器
            timeout: 超时时间
        """
        element = self.find_element(locator, timeout)
        self.logger.info(f"鼠标悬停到元素: {locator}")
        ActionChains(self.driver).move_to_element(element).perform()

    def take_screenshot(self, filename=None):
        """
        截取屏幕截图

        Args:
            filename: 截图文件名，如果为None则使用时间戳

        Returns:
            str: 截图文件路径
        """
        if filename is None:
            timestamp = time.strftime("%Y%m%d_%H%M%S")
            filename = f"screenshot_{timestamp}.png"

        # 确保截图目录存在
        screenshot_dir = "screenshots"
        if not os.path.exists(screenshot_dir):
            os.makedirs(screenshot_dir)

        filepath = os.path.join(screenshot_dir, filename)
        self.driver.save_screenshot(filepath)
        self.logger.info(f"截图已保存: {filepath}")
        return filepath

    def wait_for_page_load(self, timeout=None):
        """
        等待页面加载完成
        """
        if timeout is None:
            timeout = self.timeout

        self.logger.info("等待页面加载完成")
        WebDriverWait(self.driver, timeout).until(
            lambda driver: driver.execute_script("return document.readyState") == "complete"
        )

    def refresh_page(self):
        """
        刷新页面
        """
        self.logger.info("刷新页面")
        self.driver.refresh()
        self.wait_for_page_load()

    def go_back(self):
        """
        返回上一页
        """
        self.logger.info("返回上一页")
        self.driver.back()
        self.wait_for_page_load()

    def go_forward(self):
        """
        前进到下一页
        """
        self.logger.info("前进到下一页")
        self.driver.forward()
        self.wait_for_page_load()

    def get_current_url(self):
        """
        获取当前URL

        Returns:
            str: 当前URL
        """
        url = self.driver.current_url
        self.logger.info(f"当前URL: {url}")
        return url

    def get_page_title(self):
        """
        获取页面标题

        Returns:
            str: 页面标题
        """
        title = self.driver.title
        self.logger.info(f"页面标题: {title}")
        return title

    def accept_alert(self):
        """
        接受警告框
        """
        self.logger.info("接受警告框")
        self.driver.switch_to.alert.accept()

    def dismiss_alert(self):
        """
        取消警告框
        """
        self.logger.info("取消警告框")
        self.driver.switch_to.alert.dismiss()

    def get_alert_text(self):
        """
        获取警告框文本

        Returns:
            str: 警告框文本
        """
        text = self.driver.switch_to.alert.text
        self.logger.info(f"警告框文本: {text}")
        return text

